/*  
 * i-OSGi - Tunable Bundle Isolation for OSGi
 * Copyright (C) 2011  Sven Schulz
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.iosgi.benchmark;

import java.io.File;
import java.io.FileWriter;
import java.util.concurrent.TimeUnit;

import org.apache.felix.ipojo.annotations.Component;
import org.apache.felix.ipojo.annotations.Provides;
import org.apache.felix.ipojo.annotations.Requires;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Sven Schulz
 */
@Component(immediate = true)
@Provides(specifications = { Benchmark.class })
public class ServiceInvocation implements Benchmark {

	private static final Logger LOGGER = LoggerFactory
			.getLogger(ServiceInvocation.class);

	private static final long duration = 60000;

	@Requires
	private PingService[] pingSvcs;

	@Override
	public void perform() throws Exception {
		File f = new File("service-invocation."
				+ Long.toHexString(System.currentTimeMillis()) + ".csv");
		FileWriter w = new FileWriter(f);
		try {
			w.write("From,To,Invocations [#],Elapsed [ns],Elapsed/Invocation\n");
			LOGGER.debug(
					"performing service invocation benchmark across {} environment(s), each for {}",
					new Object[] { pingSvcs.length, duration });
			for (int i = 0; i < pingSvcs.length; i++) {
				PingService p = pingSvcs[i];
				for (int j = 0; j < pingSvcs.length; j++) {
					PingService q = pingSvcs[j];
					LOGGER.debug(
							"[{}/{}] performing service invocation test from {} to {}",
							new Object[] { i * pingSvcs.length + j + 1,
									(long) Math.pow(pingSvcs.length, 2),
									p.getEnvironmentId(), q.getEnvironmentId() });
					long ref = System.nanoTime();
					int count = p.perform(q.getEnvironmentId(), duration,
							TimeUnit.MILLISECONDS);
					long elapsed = System.nanoTime() - ref;
					long avg = Math.round(elapsed / (double) count);
					LOGGER.debug(
							"performed {} invocations in {} ns ({} ns on average)",
							new Object[] { count, elapsed, avg });
					w.write(p.getEnvironmentId() + "," + q.getEnvironmentId()
							+ "," + count + "," + elapsed + "," + avg + "\n");
				}
			}
		} finally {
			w.close();
		}
		LOGGER.debug("result written to {}", f.getAbsolutePath());
	}
}